package com.blackhorse.rabbitmq.config;

import com.blackhorse.rabbitmq.confirm.MsgSendConfirmCallBack;
import com.blackhorse.rabbitmq.confirm.MsgSendReturnCallBack;
import com.rabbitmq.client.AMQP;
import com.rabbitmq.client.impl.AMQImpl;
import org.springframework.amqp.core.*;
import org.springframework.amqp.rabbit.connection.ConnectionFactory;
import org.springframework.amqp.rabbit.core.RabbitTemplate;
import org.springframework.amqp.rabbit.transaction.RabbitTransactionManager;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.ImportResource;
import org.springframework.transaction.PlatformTransactionManager;

//rabbitMQ配置类
@Configuration
//@ImportResource("classpath:spring/spring-rabbitmq.xml")//xml配置 仅供参考
public class RabbitMQConfig {

    @Bean("rabbitTemplate")
    public RabbitTemplate rabbitTemplate(ConnectionFactory connectionFactory){
        return new RabbitTemplate(connectionFactory);
    }

    //交换机名称
    public static final String ITEM_TOPIC_EXCHANGE = "item_topic_exchange";
    //队列名称
    public static final String ITEM_QUEUE = "item_queue";

    //声明交换机
    @Bean("itemTopicExchange")
    public Exchange topicExchange() {
        return ExchangeBuilder
                .topicExchange(ITEM_TOPIC_EXCHANGE)
                .durable(true)
                .build();
    }

    //声明队列
    @Bean("itemQueue")
    public Queue itemQueue() {
        return QueueBuilder.durable(ITEM_QUEUE).build();
    }

    //绑定队列和交换机
    @Bean
    public Binding itemQueueExchange(@Qualifier("itemQueue") Queue queue,
                                     @Qualifier("itemTopicExchange") Exchange exchange) {
        return BindingBuilder
                .bind(queue)
                .to(exchange)
                .with("item.#")
                .noargs();
    }

    //--------------------------------------------------------------//
    //定义过期队列及其属性，不存在则自动创建
    @Bean("my_ttl_queue")
    public Queue myTtlQueue() {
        Queue queue = new Queue("my_ttl_queue");
        queue.getArguments().put("x-message-ttl", 6000L);//投递到该队列的消息如果没有消费都将在6秒之后被删除
        return queue;
    }

    //---------------------------------------------------------------//
    //定义定向交换机中的持久化死信队列，不存在则自动创建
    @Bean("my_dlx_queue")
    public Queue myDLXQueue() {
        return new Queue("my_dlx_queue");
    }

    //定义广播类型交换机；并绑定上述两个队列
    @Bean("my_dlx_exchange")
    public Exchange myDLXExchange() {
        return ExchangeBuilder.directExchange("my_dlx_exchange").build();
    }

    //绑定路由键my_ttl_dlx、my_max_dlx，可以将过期的消息转移到my_dlx_queue队列
    @Bean
    public Binding myTtlQueueExchange(@Qualifier("my_dlx_queue") Queue queue,
                                      @Qualifier("my_dlx_exchange") Exchange exchange){
        return BindingBuilder
                .bind(queue)
                .to(exchange)
                .with("my_ttl_dlx")
                .noargs();
    }
    @Bean
    public Binding myTtlQueueExchange2(@Qualifier("my_dlx_queue") Queue queue,
                                      @Qualifier("my_dlx_exchange") Exchange exchange){
        return BindingBuilder
                .bind(queue)
                .to(exchange)
                .with("my_max_dlx")
                .noargs();
    }
    //--------------------------- 队列设置死信交换机

    @Bean("my_ttl_dlx_queue")
    public Queue myTtlDlxQueue() {//定义过期队列及其属性，不存在则自动创建
       return QueueBuilder
               .durable("my_ttl_dlx_queue")
               .withArgument("x-message-ttl", 6000L) //投递到该队列的消息如果没有消费都将在6秒之后被投递到死信交换机
               .withArgument("x-dead-letter-exchange", "my_dlx_exchange")//设置当消息过期后投递到对应的死信交换机
               .build();
    }

    @Bean("my_max_dlx_queue")
    public Queue myMaxDlxQueue(){//定义限制长度的队列及其属性，不存在则自动创建
        Queue queue = new Queue("my_max_dlx_queue");
        queue.getArguments().put("x-max-length", 2L);//投递到该队列的消息最多2个消息，如果超过则最早的消息被删除投递到死信交换机
        queue.getArguments().put("x-dead-letter-exchange", "my_dlx_exchange");//设置当消息过期后投递到对应的死信交换机
        return queue;
    }

    @Bean("my_normal_exchange")
    public Exchange myNormalExchange(){ //定义定向交换机 根据不同的路由key投递消息
       return ExchangeBuilder.directExchange("my_normal_exchange").build();
    }

    @Bean("my_ttl_dlx")
    public Binding myTtlDlx(@Qualifier("my_ttl_dlx_queue") Queue queue,
                            @Qualifier("my_normal_exchange") Exchange exchange){
       return BindingBuilder.bind(queue).to(exchange)
                .with("my_ttl_dlx")
                .noargs();
    }

    @Bean("my_max_dlx")
    public Binding myMaxDlx(@Qualifier("my_max_dlx_queue") Queue queue,
                            @Qualifier("my_normal_exchange") Exchange exchange){
        return BindingBuilder.bind(queue).to(exchange)
                .with("my_max_dlx")
                .noargs();
    }

    //-----------------------------------//
    //定义rabbitTemplate对象操作可以在代码中方便发送消息
    @Bean("rabbitTemplate2")
    public RabbitTemplate rabbitTemplate2(ConnectionFactory connectionFactory){
        RabbitTemplate rabbitTemplate = new RabbitTemplate();
        rabbitTemplate.setConnectionFactory(connectionFactory);

        // confirm-callback="confirmCallback" 表示：消息失败回调
        rabbitTemplate.setConfirmCallback(new MsgSendConfirmCallBack());

        //return-callback="sendReturnCallback" 表示：消息失败回调 ,同时需配置mandatory="true"，否则消息则丢失
        rabbitTemplate.setReturnCallback(new MsgSendReturnCallBack());
        rabbitTemplate.setMandatory(true);
        return rabbitTemplate;
    }

    //----------------------------------------------//
    @Bean("rabbitTemplate3")
    public RabbitTemplate rabbitTemplate3(ConnectionFactory connectionFactory){
        RabbitTemplate rabbitTemplate = new RabbitTemplate();
        rabbitTemplate.setConnectionFactory(connectionFactory);

        // confirm-callback="confirmCallback" 表示：消息失败回调
        rabbitTemplate.setConfirmCallback(new MsgSendConfirmCallBack());

        //return-callback="sendReturnCallback" 表示：消息失败回调 ,同时需配置mandatory="true"，否则消息则丢失
        rabbitTemplate.setReturnCallback(new MsgSendReturnCallBack());
        rabbitTemplate.setMandatory(true);
        //channel-transacted="true" 表示：支持事务操作
        rabbitTemplate.setChannelTransacted(true);
        return rabbitTemplate;
    }

    //平台事务管理器
    @Bean("transactionManager")
    public PlatformTransactionManager transactionManager(ConnectionFactory connectionFactory){
        RabbitTransactionManager transactionManager = new RabbitTransactionManager();
        transactionManager.setConnectionFactory(connectionFactory);
        return transactionManager;
    }
}
